bitkeeper revision 1.192 (3eae50ddRBIeCAm0nByE2rOPgLLz3A)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Tue, 29 Apr 2003 10:15:57 +0000 (10:15 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Tue, 29 Apr 2003 10:15:57 +0000 (10:15 +0000)
network.c, vif.h, kernel.c:
  Removed 'dom0_ip' option from Xen. Console packets are now sent to 169.254.0.1 (DOM0's hardwired link-local address).

xen/common/kernel.c
xen/common/network.c
xen/include/xeno/vif.h
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/network/network.c

index 4ba43b24f9efdf9f402c4b1e70ecf2cbe61baa36..67602c113934caf6e7f04148bf4b9e3c2dff01ea 100644 (file)
@@ -32,7 +32,6 @@ void init_serial(void);
 void start_of_day(void);
 
 /* Command line options and variables. */
-unsigned long opt_dom0_ip = 0;
 unsigned int opt_ser_baud = 9600;  /* default baud for COM1 */
 unsigned int opt_dom0_mem = 16000; /* default kbytes for DOM0 */
 unsigned int opt_ne_base = 0; /* NE2k NICs cannot be probed */
@@ -45,7 +44,6 @@ static struct {
     void *var;
 } opts[] = {
     { "ser_baud", OPT_UINT, &opt_ser_baud },
-    { "dom0_ip",  OPT_IP,   &opt_dom0_ip },
     { "dom0_mem", OPT_UINT, &opt_dom0_mem }, 
     { "ne_base",  OPT_UINT, &opt_ne_base },
     { "ifname",   OPT_STR,  &opt_ifname },
@@ -183,11 +181,6 @@ void cmain (unsigned long magic, multiboot_info_t *mbi)
     dom0_params.num_vifs  = 1;
     dom0_params.memory_kb = opt_dom0_mem;
 
-    if ( opt_dom0_ip == 0 )
-        panic("Must specify an IP address for domain 0!\n");
-
-    add_default_net_rule(0, opt_dom0_ip); // add vfr info for dom0
-
     new_dom = do_newdomain(0, 0);
     if ( new_dom == NULL ) panic("Error creating domain 0\n");
 
@@ -506,8 +499,8 @@ int console_export(char *str, int len)
     iph->id      = 0xdead;
     iph->ttl     = 255;
     iph->protocol= 17;
-    iph->daddr   = htonl(opt_dom0_ip);
-    iph->saddr   = htonl(0xa9fe0001); 
+    iph->daddr   = htonl(0xa9fe0001);  /* 169.254.0.1 */
+    iph->saddr   = htonl(0xa9fe0001);  /* 169.254.0.1 */
     iph->tot_len = htons(hdr_size + len); 
     iph->check  = 0;
     iph->check   = compute_cksum((__u16 *)iph, sizeof(struct my_iphdr)/2); 
index f63f82e4b1004daa4a63bae4707f61ae582ba603..80d27e7bd6aca254689c7e4c4c14c4030166b474 100644 (file)
@@ -251,38 +251,6 @@ int delete_net_rule(net_rule_t *rule)
     return 0;
 }
  
-/* add_default_net_rule - Set up default network path (ie for dom0).
- * 
- * this is a utility function to route all traffic with the specified
- * ip address to the specified vif.  It's used to set up domain zero.
- */
-
-void add_default_net_rule(unsigned long vif_id, u32 ipaddr)
-{
-    net_rule_t new_rule;
-
-    //outbound rule.
-    memset(&new_rule, 0, sizeof(net_rule_t));
-    new_rule.src_addr = ipaddr;
-    new_rule.src_addr_mask = 0xffffffff;
-    new_rule.src_vif = vif_id;
-    new_rule.dst_vif = VIF_PHYSICAL_INTERFACE;
-    new_rule.action = NETWORK_ACTION_ACCEPT;
-    new_rule.proto = NETWORK_PROTO_ANY;
-    add_net_rule(&new_rule);
-
-    //inbound rule;
-    memset(&new_rule, 0, sizeof(net_rule_t));
-    new_rule.dst_addr = ipaddr;
-    new_rule.dst_addr_mask = 0xffffffff;
-    new_rule.src_vif = VIF_ANY_INTERFACE;
-    new_rule.dst_vif = vif_id;
-    new_rule.action = NETWORK_ACTION_ACCEPT;
-    new_rule.proto = NETWORK_PROTO_ANY;
-    add_net_rule(&new_rule);
-
-}
-
 /* print_net_rule - Print a single net rule.
  */
 
@@ -371,6 +339,8 @@ static net_vif_t *net_find_rule(u8 nproto, u8 tproto, u32 src_addr,
         if ( ((ent->r.src_vif == src_vif)
               || (ent->r.src_vif == VIF_ANY_INTERFACE)) &&
 
+             (src_vif != ent->r.dst_vif) &&
+
              (!((ent->r.src_addr ^ src_addr) & ent->r.src_addr_mask )) &&
              (!((ent->r.dst_addr ^ dst_addr) & ent->r.dst_addr_mask )) &&
              (!((ent->r.src_port ^ src_port) & ent->r.src_port_mask )) &&
@@ -504,9 +474,10 @@ long do_network_op(network_op_t *u_network_op)
 
     case NETWORK_OP_GETRULELIST:
     {
-        // This should eventually ship a rule list up to the VM
-        // to be printed in its procfs.  For now, we just print the rules.
-        
+        /*
+         * This should ship a rule list up to the guest OS. For now
+         * we just dump the rules to our own console.
+         */
         print_net_rule_list();
     }
     break;
@@ -525,9 +496,29 @@ long do_network_op(network_op_t *u_network_op)
 
 void __init net_init (void)
 {
+    net_rule_t new_rule;
+
     net_rule_list = NULL;
-    net_vif_cache = kmem_cache_create("net_vif_cache", sizeof(net_vif_t),
-                                    0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-    net_rule_cache = kmem_cache_create("net_rule_cache", sizeof(net_rule_ent_t),
-                                    0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+    net_vif_cache = kmem_cache_create("net_vif_cache", 
+                                      sizeof(net_vif_t),
+                                      0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+    net_rule_cache = kmem_cache_create("net_rule_cache", 
+                                       sizeof(net_rule_ent_t),
+                                       0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+    /* Bootstrap outbound rule. */
+    memset(&new_rule, 0, sizeof(net_rule_t));
+    new_rule.src_vif = 0;
+    new_rule.dst_vif = VIF_PHYSICAL_INTERFACE;
+    new_rule.action = NETWORK_ACTION_ACCEPT;
+    new_rule.proto = NETWORK_PROTO_ANY;
+    add_net_rule(&new_rule);
+
+    /* Bootstrap inbound rule. */
+    memset(&new_rule, 0, sizeof(net_rule_t));
+    new_rule.src_vif = VIF_ANY_INTERFACE;
+    new_rule.dst_vif = 0;
+    new_rule.action = NETWORK_ACTION_ACCEPT;
+    new_rule.proto = NETWORK_PROTO_ANY;
+    add_net_rule(&new_rule);
 }
index de83e7e76ba8517a4dabde9d6c0b07b5af79244d..4fb2e275d1460d27ab9362ec23d8145a431bed51 100644 (file)
@@ -81,7 +81,6 @@ do {                                                               \
 net_vif_t *create_net_vif(int domain);
 void destroy_net_vif(net_vif_t *vif);
 void unlink_net_vif(net_vif_t *vif);
-void add_default_net_rule(unsigned long vif_id, u32 ipaddr);
 net_vif_t *net_get_target_vif(u8 *data, unsigned int len, net_vif_t *src_vif);
 net_vif_t *find_vif_by_id(unsigned long id);
 
index 03f9939e4e79029b62ef1da62e37f1500e9a1201..7cf0fecbec68259f9fb8e9afdd3b0406f1fd9fd2 100644 (file)
@@ -58,6 +58,7 @@ struct net_private
     net_ring_t *net_ring;
     net_idx_t  *net_idx;
     spinlock_t tx_lock;
+    unsigned int idx; /* Domain-specific index of this VIF. */
 
     /*
      * {tx,rx}_skbs store outstanding skbuffs. The first entry in each
@@ -412,6 +413,96 @@ static struct net_device_stats *network_get_stats(struct net_device *dev)
 }
 
 
+/*
+ * This notifier is installed for domain 0 only.
+ * All other domains have VFR rules installed on their behalf by domain 0
+ * when they are created. For bootstrap, Xen creates wildcard rules for
+ * domain 0 -- this notifier is used to detect when we find our proper
+ * IP address, so we can poke down proper rules and remove the wildcards.
+ */
+static int inetdev_notify(struct notifier_block *this, 
+                          unsigned long event, 
+                          void *ptr)
+{
+    struct in_ifaddr  *ifa  = (struct in_ifaddr *)ptr; 
+    struct net_device *dev = ifa->ifa_dev->dev;
+    struct list_head  *ent;
+    struct net_private *np;
+    int idx = -1;
+    network_op_t op;
+    static int removed_bootstrap_rules = 0;
+
+    list_for_each ( ent, &dev_list )
+    {
+        np  = list_entry(dev_list.next, struct net_private, list);
+        if ( np->dev == dev )
+            idx = np->idx;
+    }
+
+    if ( idx == -1 )
+        goto out;
+    
+    memset(&op, 0, sizeof(op));
+    op.u.net_rule.proto         = NETWORK_PROTO_ANY;
+    op.u.net_rule.action        = NETWORK_ACTION_ACCEPT;
+
+    if ( event == NETDEV_UP )
+        op.cmd = NETWORK_OP_ADDRULE;
+    else if ( event == NETDEV_DOWN )
+        op.cmd = NETWORK_OP_DELETERULE;
+    else
+        goto out;
+
+    op.u.net_rule.src_vif       = idx;
+    op.u.net_rule.dst_vif       = VIF_PHYSICAL_INTERFACE;
+    op.u.net_rule.src_addr      = ntohl(ifa->ifa_address);
+    op.u.net_rule.src_addr_mask = ~0UL;
+    op.u.net_rule.dst_addr      = 0;
+    op.u.net_rule.dst_addr_mask = 0;
+    (void)HYPERVISOR_network_op(&op);
+    
+    op.u.net_rule.src_vif       = VIF_ANY_INTERFACE;
+    op.u.net_rule.dst_vif       = idx;
+    op.u.net_rule.src_addr      = 0;
+    op.u.net_rule.src_addr_mask = 0;    
+    op.u.net_rule.dst_addr      = ntohl(ifa->ifa_address);
+    op.u.net_rule.dst_addr_mask = ~0UL;
+    (void)HYPERVISOR_network_op(&op);
+
+    /*
+     * Xen creates a pair of bootstrap rules which allows domain 0 to
+     * send and receive any packet. These rules can be removed once we
+     * have configured an IP address.
+     */
+    if ( (idx == 0) && (event == NETDEV_UP) && !removed_bootstrap_rules )
+    {
+        memset(&op, 0, sizeof(op));
+        op.cmd = NETWORK_OP_DELETERULE;
+        op.u.net_rule.proto         = NETWORK_PROTO_ANY;
+        op.u.net_rule.action        = NETWORK_ACTION_ACCEPT;
+
+        op.u.net_rule.src_vif       = 0;
+        op.u.net_rule.dst_vif       = VIF_PHYSICAL_INTERFACE;
+        (void)HYPERVISOR_network_op(&op);
+
+        op.u.net_rule.src_vif       = VIF_ANY_INTERFACE;
+        op.u.net_rule.dst_vif       = 0;
+        (void)HYPERVISOR_network_op(&op);
+
+        removed_bootstrap_rules = 1;
+    }
+    
+ out:
+    return NOTIFY_DONE;
+}
+
+static struct notifier_block notifier_inetdev = {
+    .notifier_call  = inetdev_notify,
+    .next           = NULL,
+    .priority       = 0
+};
+
+
 int __init init_module(void)
 {
     int i, fixmap_idx=-1, err;
@@ -420,6 +511,14 @@ int __init init_module(void)
 
     INIT_LIST_HEAD(&dev_list);
 
+    /*
+     * Domain 0 must poke its own network rules as it discovers its IP
+     * addresses. All other domains have a privileged "parent" to do this
+     * for them at start of day.
+     */
+    if ( start_info.dom_id == 0 )
+        (void)register_inetaddr_notifier(&notifier_inetdev);
+
     for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
     {
         if ( start_info.net_rings[i] == 0 )
@@ -441,6 +540,7 @@ int __init init_module(void)
         np = dev->priv;
         np->net_ring = (net_ring_t *)fix_to_virt(FIX_NETRING0_BASE+fixmap_idx);
         np->net_idx  = &HYPERVISOR_shared_info->net_idx[i];
+        np->idx      = i;
 
         SET_MODULE_OWNER(dev);
         dev->open            = network_open;
@@ -482,6 +582,9 @@ static void cleanup_module(void)
         unregister_netdev(dev);
         kfree(dev);
     }
+
+    if ( start_info.dom_id == 0 )
+        (void)unregister_inetaddr_notifier(&notifier_inetdev);
 }